﻿using log4net;
using log4net.Appender;
using log4net.Config;
using log4net.Core;
using log4net.Layout;
using log4net.Repository.Hierarchy;
using System;
using System.Collections.Concurrent;
using System.IO;

public static class Log4
{

    

    // 默认基础日志目录（应用程序目录）（可配置）
    private static string _baseLogDirectory = AppDomain.CurrentDomain.BaseDirectory;

    // 缓存已创建的日志记录器（线程安全）
    private static readonly ConcurrentDictionary<string, ILog> _loggers =
        new ConcurrentDictionary<string, ILog>();

    // 日志等级映射
    private static readonly ConcurrentDictionary<string, Level> _levelMap = new ConcurrentDictionary<string, Level>
    {
        ["FATAL"] = Level.Fatal,
        ["ERROR"] = Level.Error,
        ["WARN"] = Level.Warn,
        ["INFO"] = Level.Info,
        ["DEBUG"] = Level.Debug
    };
    /// <summary>
    /// 获取应用程序根目录（软件安装位置）
    /// </summary>
    private static string GetApplicationRootPath()
    {
        try
        {
            // 优先使用应用程序域基础目录
            string appRoot = AppDomain.CurrentDomain.BaseDirectory;

            // 处理ClickOnce部署的特殊情况
            if (appRoot.Contains("appref-ms"))
            {
                appRoot = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
            }

            // 确保路径格式正确
            return Path.GetFullPath(appRoot).TrimEnd(Path.DirectorySeparatorChar);
        }
        catch
        {
            // 备用方案：当前工作目录
            return Directory.GetCurrentDirectory();
        }
    }
    /// <summary>
    /// 设置基础日志目录（默认已设为应用根目录）
    /// </summary>
    public static string BaseLogDirectory
    {
        get => _baseLogDirectory;
        set
        {
            if (!Directory.Exists(value))
                Directory.CreateDirectory(value);
            _baseLogDirectory = value;
        }
    }
    /// <summary>
    /// 初始化日志系统
    /// </summary>
    static Log4()
    {
        // 确保基础目录存在
        if (!Directory.Exists(BaseLogDirectory))
            Directory.CreateDirectory(BaseLogDirectory);
    }
    


    #region 核心日志方法

    /// <summary>
    /// 记录日志到指定位置
    /// </summary>
    /// <param name="relativePath">相对路径（如 "Operations/Actions.log"）</param>
    /// <param name="message">日志内容</param>
    public static void Log(string relativePath, string message)
    {
        Log(relativePath, message, Level.Info);
    }

    /// <summary>
    /// 记录日志到指定位置（带日志等级）
    /// </summary>
    public static void Log(string relativePath, string message, Level level)
    {
        var logger = GetLoggerForPath(relativePath);
        logger.Logger.Log(typeof(Log4), level, message, null);
    }

    /// <summary>
    /// 记录日志到指定位置（带日志等级名称）
    /// </summary>
    public static void Log(string relativePath, string message, string levelName)
    {
        var level = GetLogLevel(levelName);
        Log(relativePath, message, level);
    }

    #endregion
    #region 标准等级快捷方法

    public static void Fatal(string relativePath, string message)
        => Log(relativePath, message, Level.Fatal);

    public static void Error(string relativePath, string message)
        => Log(relativePath, message, Level.Error);

    public static void Warn(string relativePath, string message)
        => Log(relativePath, message, Level.Warn);

    public static void Info(string relativePath, string message)
        => Log(relativePath, message, Level.Info);

    public static void Debug(string relativePath, string message)
        => Log(relativePath, message, Level.Debug);

    #endregion
    #region 内部实现方法

    /// <summary>
    /// 获取日志等级对象
    /// </summary>
    private static Level GetLogLevel(string levelName)
    {
        if (string.IsNullOrWhiteSpace(levelName))
            return Level.Info;

        return _levelMap.TryGetValue(levelName.ToUpper(), out var level)
            ? level
            : Level.Info;
    }

    /// <summary>
    /// 为指定路径获取或创建日志记录器
    /// </summary>
    private static ILog GetLoggerForPath(string relativePath)
    {
        // 标准化路径格式
        var normalizedPath = NormalizePath(relativePath);

        return _loggers.GetOrAdd(normalizedPath, path =>
        {
            // 创建新的日志记录器
            var loggerName = $"Logger_{path.Replace("/", "_")}";
            var logger = LogManager.GetLogger(loggerName);

            // 配置专属的FileAppender
            ConfigureFileAppender(loggerName, path);

            return logger;
        });
    }

    /// <summary>
    /// 标准化路径格式
    /// </summary>
    private static string NormalizePath(string path)
    {
        if (Path.IsPathRooted(path))
            return path.Replace('\\', '/').TrimStart('/');

        return path
            .Replace('\\', '/')
            .TrimStart('/')
            .ToLowerInvariant();
    }

    /// <summary>
    /// 为指定日志记录器配置文件输出
    /// </summary>
    private static void ConfigureFileAppender(string loggerName, string relativePath)
    {
        var hierarchy = (Hierarchy)LogManager.GetRepository();
        var logger = hierarchy.GetLogger(loggerName) as Logger;

        if (logger == null) return;

        // 创建文件路径
        string fullPath = Path.Combine(BaseLogDirectory, relativePath);
        string directory = Path.GetDirectoryName(fullPath);

        // 确保目录存在
        if (!Directory.Exists(directory))
        {
            Directory.CreateDirectory(directory);
        }

        // 创建文件追加器
        var appender = new RollingFileAppender
        {
            Name = $"{loggerName}_Appender",
            File = fullPath,
            AppendToFile = true,
            RollingStyle = RollingFileAppender.RollingMode.Composite,
            MaxSizeRollBackups = 30, // 保留30个备份文件
            MaximumFileSize = "10MB", // 每个文件最大10MB
            DatePattern = "_yyyyMMdd'.log'", // 按日期滚动
            StaticLogFileName = false,
            Layout = new PatternLayout("%date [%thread] %-5level - %message%newline")
        };

        // 激活配置
        appender.ActivateOptions();

        // 添加到日志记录器
        logger.AddAppender(appender);
        logger.Level = Level.All;
        logger.Additivity = false; // 不继承根记录器的Appender
    }

    #endregion
    #region 高级功能

    /// <summary>
    /// 添加自定义日志等级
    /// </summary>
    public static void AddCustomLevel(string name, int value)
    {
        var level = new Level(value, name.ToUpper());
        _levelMap[name.ToUpper()] = level;
    }

    /// <summary>
    /// 设置日志格式
    /// </summary>
    public static void SetPattern(string relativePath, string pattern)
    {
        var normalizedPath = NormalizePath(relativePath);
        if (_loggers.TryGetValue(normalizedPath, out var logger))
        {
            var appender = GetAppenderForLogger(logger);
            if (appender != null)
            {
                appender.Layout = new PatternLayout(pattern);
                appender.ActivateOptions();
            }
        }
    }

    /// <summary>
    /// 获取指定日志记录器的Appender
    /// </summary>
    private static RollingFileAppender GetAppenderForLogger(ILog logger)
    {
        var hierarchy = (Hierarchy)LogManager.GetRepository();
        var log = hierarchy.GetLogger(logger.Logger.Name) as Logger;

        if (log != null)
        {
            foreach (var appender in log.Appenders)
            {
                if (appender is RollingFileAppender rfa)
                {
                    return rfa;
                }
            }
        }
        return null;
    }

    #endregion
}